<?php

namespace Yolo\Components\Gateway;

use Hyperf\HttpServer\Server;
use Throwable;
use Yolo\Errors\RpcException;

class GatewayRequest extends Server
{

    public function onRequest($request, $response): void
    {
        $start = $request->server['request_time_float'] ?? microtime(true);

        $isOk = true;

        $response->header('Content-Type', 'application/json');

        try {
            parent::onRequest($request, $response);
        } catch (Throwable $throwable) {

            $isOk = false;

            $error = $this->handleException($throwable);

            $response->status($error['http']['status']);
            $response->end(json_encode($error));

            return;
        } finally {

            $end = microtime(true);

            logInfo([
                'action' => 'request',
                'message' => $isOk ? 'ok' : 'nok',
                'data' => [
                    'duration' => round(($end - $start) * 1000000),
                    'uri' => $request->server['request_uri'],
                    'method' => $request->server['request_method'],
                ]
            ]);
        }

    }

    private function handleException(Throwable $throwable): array
    {
        if ($throwable instanceof RpcException) {

            logError([
                'action' => 'request',
                'message' => $throwable->getMessage(),
                'data' => [
                    'error' => $throwable->json(),
                    'trace' => $throwable->getTrace(),
                ]
            ]);

            return $throwable->json();
        }

        logError([
            'action' => 'request',
            'message' => $throwable->getMessage(),
            'data' => [
                'error' => [
                    'code' => $throwable->getCode(),
                    'message' => $throwable->getMessage(),
                    'trace' => $throwable->getTrace(),
                ]
            ]
        ]);

        return [
            'code' => -1,
            'symbol' => 'system_error',
            'message' => $throwable->getMessage() ?: 'Server Internal Error.',
            'metadata' => [],
            'http' => [
                'status' => 500,
            ]
        ];

    }
}
